/* * ConcreteSplitViewer program for analazing splits. * Copyright (C) 2006-2007 Mytinski Leonid (Leonid.Mytinski@gmail.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ /* * OSVReader.java * * Created on 27 ���� 2006 �., 19:42 * * To change this template, choose Tools | Template Manager * and open the template in the editor. */ package ru.concretesoft.concretesplitviewer; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * * @author Mytinski Leonid * * Reader of OSV format files */ public class OSVReader extends SplitReader{ private final Boolean DEBUG = false; private File file; private FileInputStream fIS; private String all; private String nameOfComp; private List<String> groupsNames; private List<Group> allGroups; private String encoding = "CP1251"; private int version = 0; // 0 - unknown version private String eventDescription = ""; // Event description if it presents in file /** Creates a new instance of OSVReader * @param file splits file * @throws java.io.IOException * @throws ru.concretesoft.concretesplitviewer.NotRightFormatException */ public OSVReader(File file) throws IOException, NotRightFormatException { this.file=file; fIS = new FileInputStream(file); int length = (int)file.length(); byte[] s = null; try { s = new byte[length]; } catch (java.lang.OutOfMemoryError e) { throw new IOException("File too long to fit into memory."); } fIS.read(s); try{ all=new String(s,encoding); } catch(UnsupportedEncodingException e){ all = ""; } String[] groups = all.split("#"); if (isVersionOne(file, groups)) { // Already parsed by isVersionOne() } else { // Not 'Version 1' groupsNames = new ArrayList<String>(); LinkedList<Group> allGroupsTemp = new LinkedList<Group>(); try{ for(int i=1;i<groups.length;i++){ allGroupsTemp.add(new Group()); String[] tmp = groups[i].split(" ",2); groupsNames.add(tmp[0]); allGroupsTemp.getLast().setName(tmp[0]); tmp = groups[i].split("\n"); String[] tmp1 = tmp[0].split("\\s*,\\s*"); int l = (int)((new Double(tmp1[2].split("\\s+")[0])).doubleValue()*1000); int nCP = (new Integer(tmp1[1].split("\\s+")[0])).intValue()+1; Distance d = new Distance(tmp1[0],l,nCP); Iterator<Group> it = allGroupsTemp.iterator(); while(it.hasNext()){ Distance dTmp = it.next().getDistance(); if(dTmp == null) break; if(dTmp.equals(d)){ dTmp.setName(dTmp.getName()+" "+d.getName()); d=dTmp; break; } } allGroupsTemp.getLast().setDistance(d); for(int j=1;j<tmp.length;j++){ String[] tmp2 = tmp[j].split("\\s+"); // Time totTime = new Time(tmp2[2],3); Time[] splits = new Time[nCP]; for(int k = 0; k<nCP;k++){ try{ splits[k]=new Time(tmp2[k+3],2); } catch(java.lang.NumberFormatException e){ splits[k]=new Time(0,2); } catch(java.lang.ArrayIndexOutOfBoundsException e){ splits[k]=new Time(0,2); } } Athlete a = new Athlete(tmp2[0],tmp2[1],splits,allGroupsTemp.getLast()); } } }catch(ArrayIndexOutOfBoundsException e){ throw new NotRightFormatException(file, "OSV", " array index of bound."); } Iterator<Group> it = allGroupsTemp.iterator(); while(it.hasNext()){ Distance d = it.next().getDistance(); if(d.getLengthOfDist(1) < 0){ d.setLengthsOfDists(Tools.calculatLengthsOfLaps(d.getGroups())); } } allGroups = new ArrayList<Group>(allGroupsTemp); } if((groupsNames==null)||(groupsNames.size()==0)){ throw new NotRightFormatException(file, "OSV", " unknown reason."); } } /** * Parse OSV-file as 'Version 1' * @param groups Strings that produced by splitting file with '#' * @return true if successful, false if any kind of error found */ private boolean isVersionOne(File file, String[] groups) throws NotRightFormatException { if (groups.length <= 0){ System.err.println("Please check are there records in file. May be it is empty."); return false; } String[] headerLines = groups[0].split("\n"); if (headerLines.length <= 0) { System.out.println("It is not 'Version 1' OSV-file. No header lines."); return false; } Pattern p = Pattern.compile(".*Version[ \\t]+(1)\\s*"); Matcher m = p.matcher(headerLines[0]); if (! m.matches()) { System.out.println("It is not 'Version 1' OSV-file. First line not contain 'Version 1'."); return false; } System.out.println("It seems 'Version 1' OSV-file."); if (headerLines.length < 5) { System.err.println("Bad 'Version 1' file format: header contains less than 5 lines."); return false; } /* * Parse header lines and find interesting descriptors */ int nameStart = 0, nameEnd = 0, resultStart = 0, resultEnd = 0, splitStart = 0; boolean namePresented = false, resultPresented = false, splitPresented = false; Pattern pName = Pattern.compile(".*@NAME(.+),(.+)\\s*"); Pattern pResult = Pattern.compile(".*@RESULT(.+),(.+)\\s*"); Pattern pSplits = Pattern.compile(".*@SPLITS[ \\t]+(\\d+)\\s*"); for (int i = 1; i < headerLines.length; i++) { Matcher mName = pName.matcher(headerLines[i]); if (mName.matches()) { nameStart = Integer.parseInt(mName.group(1).trim()); nameEnd = Integer.parseInt(mName.group(2).trim()); nameEnd = nameEnd + nameStart - 1; namePresented = true; continue; } Matcher mResult = pResult.matcher(headerLines[i]); if (mResult.matches()) { resultStart = Integer.parseInt(mResult.group(1).trim()); resultEnd = Integer.parseInt(mResult.group(2).trim()); resultEnd = resultEnd + resultStart - 1; resultPresented = true; continue; } Matcher mSplits = pSplits.matcher(headerLines[i]); if (mSplits.matches()) { splitStart = Integer.parseInt(mSplits.group(1)); splitPresented = true; continue; } // Here is line that doesn't match NAME, nor RESULT, nor SPLITS. // May be it is event description. // So it should be used as Title for main window. } // Check if all interesting descriptors presented if (! namePresented) { System.err.println("Bad 'Version 1' file format: @NAME is not presented."); return false; } if (! resultPresented) { System.err.println("Bad 'Version 1' file format: @RESULT is not presented."); return false; } if (! splitPresented) { System.err.println("Bad 'Version 1' file format: @SPLITS is not presented."); return false; } eventDescription = headerLines[4].trim(); // All interesting descriptors presented. // Parse. groupsNames = new ArrayList<String>(); LinkedList<Group> allGroupsTemp = new LinkedList<Group>(); try{ for(int i=1; i < groups.length; i++){ allGroupsTemp.add(new Group()); // Split all group lines String[] groupLines = groups[i].split("\\n"); // Parse first line in group: find name, number of points and distance String groupName = ""; int groupPoints = 0; int groupDistance = 0; Pattern pGroup = Pattern.compile("[ \\t]*([^\\s]+)[ \\t]*,[ \\t]*(\\d+).*,[ \\t]*(\\d+)\\.(\\d+).*\\s*"); Matcher mGroup = pGroup.matcher(groupLines[0]); if (! mGroup.matches()) { System.err.println("Bad 'Version 1' file format. Bad group description line: '"+groupLines[0]+"'"); return false; } else { } groupName = mGroup.group(1); groupPoints = Integer.parseInt(mGroup.group(2)); groupDistance = 1000 * Integer.parseInt(mGroup.group(3)) + Integer.parseInt(mGroup.group(4)); Distance d = new Distance(groupName, groupDistance, groupPoints + 1); // Find equal distance in other groups and store this fact Iterator<Group> it = allGroupsTemp.iterator(); while(it.hasNext()){ Distance dTmp = it.next().getDistance(); if(dTmp == null) break; if(dTmp.equals(d)){ dTmp.setName(dTmp.getName()+" "+d.getName()); d=dTmp; break; } } groupsNames.add(groupName); allGroupsTemp.getLast().setDistance(d); allGroupsTemp.getLast().setName(groupName); if (DEBUG) System.out.println(groupName); // Parse each line in the group for (int j = 1; j < groupLines.length; j++) { String athleteName = ""; String athleteResult = ""; Time[] athleteSplits = new Time[groupPoints + 1]; if (groupLines[j].length() < nameEnd) { System.err.println("Bad 'Version 1' file format. Length of line: '"+groupLines[j]+"' is not enough for @NAME."); return false; } else { athleteName = groupLines[j].substring(nameStart - 1, nameEnd); } if (groupLines[j].length() < resultEnd) { System.err.println("Bad 'Version 1' file format. Length of line: '"+groupLines[j]+"' is not enough for @RESULT."); return false; } else { athleteResult = groupLines[j].substring(resultStart - 1, resultEnd); } if (groupLines[j].length() < splitStart) { System.err.println("Bad 'Version 1' file format. Length of line: '"+groupLines[j]+"' is not enough for @SPLITS."); return false; } else { if (DEBUG) System.out.println(groupLines[j]); String[] theSplits = groupLines[j].substring(splitStart - 1).trim().split("\\s+"); for(int k = 0; k < groupPoints + 1; k++){ try{ athleteSplits[k] = new Time(theSplits[k],2); } catch(java.lang.NumberFormatException e){ athleteSplits[k] = new Time(0,2); } catch(java.lang.ArrayIndexOutOfBoundsException e){ athleteSplits[k] = new Time(0,2); } } } String[] athleteNames = athleteName.split("[ \\t]+"); Athlete a = new Athlete((athleteNames.length>0?(athleteNames[0].trim()):""), (athleteNames.length>1?(athleteNames[1].trim()):""), athleteSplits, allGroupsTemp.getLast(), 1900, athleteResult); } } }catch(ArrayIndexOutOfBoundsException e){ return false; } catch(NumberFormatException nfe) { throw new NotRightFormatException(file, "OSV version 1", "bad number format: " + nfe.getMessage()); } Iterator<Group> it = allGroupsTemp.iterator(); while(it.hasNext()){ Distance d = it.next().getDistance(); if(d.getLengthOfDist(1) < 0){ d.setLengthsOfDists(Tools.calculatLengthsOfLaps(d.getGroups())); } } allGroups = new ArrayList<Group>(allGroupsTemp); return true; } public List<String> getGroupsNames() { return groupsNames; } public List<Group> getAllGroups() { return allGroups; } public Group getGroup(String name) { int index = groupsNames.indexOf(name); return allGroups.get(index); } public Group getGroup(int number) { return allGroups.get(number); } public List<Group> getGroupsByDist(int number) { return null; } public String getFileName() { return file.getName(); } public String getEventDescription() { return eventDescription; } }